package com.travel.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.travel.context.UserContext;
import com.travel.dto.QrCodeDto;
import com.travel.dto.TravelProductAddDTO;
import com.travel.dto.TravelProductDTO;
import com.travel.dto.TravelRegistrationDTO;
import com.travel.exception.BusinessException;
import com.travel.mapper.TicketRegistrationMapper;
import com.travel.pojo.Member;
import com.travel.pojo.TravelOrderInfo;
import com.travel.pojo.TravelProducts;
import com.travel.pojo.TravelRegistration;
import com.travel.result.PageResult;
import com.travel.service.IMemberService;
import com.travel.service.TicketRegistrationService;
import com.travel.service.TravelProductService;
import com.travel.vo.OrderVO;
import com.travel.vo.TravelProductVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: libin
 * Date: 2025/6/16 15:58
 * Description:
 **/
@Service
public class TicketRegistrationServiceImpl extends ServiceImpl<TicketRegistrationMapper, TravelRegistration> implements TicketRegistrationService {


    @Autowired
    private TicketRegistrationMapper travelOrderInfoMapper;

    @Autowired
    private TravelProductService travelProductService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private QrCodeService qrCodeService;

    @Autowired
    private IMemberService memberService;
    @Override
    public Integer register(TravelRegistrationDTO dto) {
        // 1. 参数校验
        if (dto.getAdultCount() == null || dto.getAdultCount() <= 0) {
            throw new BusinessException("成人数量必须大于0");
        }

        if (dto.getAdultPrice() == null || dto.getAdultPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("成人单价必须大于0");
        }

        if (dto.getChildCount() == null) {
            dto.setChildCount(0); // 默认0个儿童
        }

        if (dto.getChildCount() < 0) {
            throw new BusinessException("儿童数量不能为负数");
        }

        if (dto.getChildCount() > 0 &&
                (dto.getChildPrice() == null || dto.getChildPrice().compareTo(BigDecimal.ZERO) <= 0)) {
            throw new BusinessException("儿童单价必须大于0");
        }

        // 2. 计算总价（如果前端没有传递）
        if (dto.getTotalPrice() == null) {
            BigDecimal total = dto.getAdultPrice().multiply(BigDecimal.valueOf(dto.getAdultCount()));
            if (dto.getChildCount() > 0) {
                total = total.add(dto.getChildPrice().multiply(BigDecimal.valueOf(dto.getChildCount())));
            }
            dto.setTotalPrice(total);
        }

            // 3. 转换DTO为实体
            TravelRegistration registration = new TravelRegistration();
            BeanUtils.copyProperties(dto, registration);
            registration.setCreateTime(LocalDateTime.now());// 设置创建时间
            registration.setUserId(UserContext.getCurrentId());
            registration.setStatus(0);
            registration.setOrderNo(generateOrderNo());
            // 4. 保存报名信息
            save(registration);

            // 5. 返回成功结果，包含报名ID
            return registration.getId();
    }

    // 生成订单号示例
    private String generateOrderNo() {
        return System.currentTimeMillis() + String.valueOf(new Random().nextInt(1000));
    }
    @Override
    public boolean pay(Integer ticketId) {
        TravelRegistration registration = getById(ticketId);
        if (ObjectUtil.isEmpty(registration)){
            throw new BusinessException("报名信息不存在");
        }
        registration.setStatus(1); // 更改为已支付
        return updateById(registration);
    }

/*
    @Override
    public PageResult getOrderInfoList(Integer pageNum, Integer pageSize, Integer status) {
        // 1. 构建分页对象
        Page<TravelRegistration> page = new Page<>(pageNum, pageSize);

        // 2. 构建查询条件
        LambdaQueryWrapper<TravelRegistration> queryWrapper = new LambdaQueryWrapper<>();



        // 按支付状态查询
        if (status != null) {
            queryWrapper.eq(TravelRegistration::getStatus, status);
        }

        // 3. 执行分页查询
        IPage<TravelRegistration> orderPage = travelOrderInfoMapper.selectPage(page, queryWrapper);

        // 如果没有订单记录，直接返回空结果
        if (orderPage.getRecords().isEmpty()) {
            return new PageResult();
        }

        // 4. 提取所有订单关联的产品ID
        List<Integer> productIds = orderPage.getRecords().stream()
                .map(TravelRegistration::getProductId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // 5. 使用MP批量查询产品名称
        Map<Integer, String> productNameMap;
        if (!productIds.isEmpty()) {
            // 假设产品实体类为TravelProduct
            // 假设产品Mapper为TravelProductMapper
            LambdaQueryWrapper<TravelProducts> productQueryWrapper = new LambdaQueryWrapper<>();
            productQueryWrapper.in(TravelProducts::getId, productIds)
                    .select(TravelProducts::getId, TravelProducts::getName);

            List<TravelProducts> products = travelProductService.list(productQueryWrapper);

            // 转换为ID到名称的映射
            productNameMap = products.stream()
                    .collect(Collectors.toMap(TravelProducts::getId, TravelProducts::getName));
        } else {
            productNameMap = new HashMap<>();
        }

        // 6. 转换结果为VO对象并设置相关属性
        List<OrderVO> orderVos = orderPage.getRecords().stream()
                .map(order -> {
                    OrderVO orderVO = BeanUtil.copyProperties(order, OrderVO.class);
                    // 设置状态文本描述
                    orderVO.setStatusText(getStatusText(order.getStatus()));
                    // 设置产品名称
                    if (order.getProductId() != null) {
                        orderVO.setProductName(productNameMap.getOrDefault(order.getProductId(), "未知产品"));
                    } else {
                        orderVO.setProductName("未知产品");
                    }
                    return orderVO;
                })
                .peek(order -> {
                    // 从缓存中获取二维码
                    String codeStr = stringRedisTemplate.opsForValue().get("order:" + order.getOrderNo());
                    if (codeStr != null) {
                        order.setQrCodeBase64(codeStr);
                    }
                })
                .collect(Collectors.toList());

        // 7. 构建分页结果
        PageResult pageResult = new PageResult();
        pageResult.setRecords(orderVos);
        pageResult.setTotal(orderPage.getTotal());

        return pageResult;
    }
*/

    @Override
    public PageResult getOrderInfoList(Integer pageNum, Integer pageSize, String status) {
        // 1. 构建分页对象 - 问题点：pageSize未校验，默认值可能导致分页不符预期
        Page<TravelRegistration> page = new Page<>(pageNum, pageSize);

        // 2. 构建查询条件
        LambdaQueryWrapper<TravelRegistration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TravelRegistration::getUserId, UserContext.getCurrentId());
        // 按支付状态查询
        if (!ObjectUtil.equals(status, "null")) {
            queryWrapper.eq(TravelRegistration::getStatus, status);
        }


        // 添加时间排序（降序）
        queryWrapper.orderByDesc(TravelRegistration::getCreateTime);

        // 3. 执行分页查询
        IPage<TravelRegistration> orderPage = travelOrderInfoMapper.selectPage(page, queryWrapper);

        // 打印分页查询关键参数和结果，用于调试
        System.out.println("分页查询参数：pageNum=" + pageNum + ", pageSize=" + pageSize);
        System.out.println("查询结果：total=" + orderPage.getTotal() + ", size=" + orderPage.getSize()
                + ", current=" + orderPage.getCurrent() + ", pages=" + orderPage.getPages());

        // 如果没有订单记录，直接返回空结果
        if (orderPage.getRecords().isEmpty()) {
            return new PageResult();
        }

        // 4. 提取所有订单关联的产品ID
        List<Integer> productIds = orderPage.getRecords().stream()
                .map(TravelRegistration::getProductId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // 5. 使用MP批量查询产品名称和图片
        Map<Integer, TravelProductDTO> productMap;
        if (!productIds.isEmpty()) {
            LambdaQueryWrapper<TravelProducts> productQueryWrapper = new LambdaQueryWrapper<>();
            productQueryWrapper.in(TravelProducts::getId, productIds)
                    .select(TravelProducts::getId, TravelProducts::getName, TravelProducts::getImageUrl);

            List<TravelProducts> products = travelProductService.list(productQueryWrapper);

            productMap = products.stream()
                    .collect(Collectors.toMap(
                            TravelProducts::getId,
                            product -> {
                                TravelProductDTO dto = new TravelProductDTO();
                                dto.setId(product.getId());
                                dto.setName(product.getName());
                                dto.setImageUrl(product.getImageUrl());
                                return dto;
                            }
                    ));
        } else {
            productMap = new HashMap<>();
        }

        // 6. 转换结果为VO对象并设置相关属性
        List<OrderVO> orderVos = orderPage.getRecords().stream()
                .map(order -> {
                    OrderVO orderVO = BeanUtil.copyProperties(order, OrderVO.class);
                    orderVO.setStatusText(getStatusText(order.getStatus()));

                    if (order.getProductId() != null) {
                        TravelProductDTO product = productMap.getOrDefault(order.getProductId(), null);
                        if (product != null) {
                            orderVO.setProductName(product.getName());
                            orderVO.setImg(product.getImageUrl());
                        } else {
                            orderVO.setProductName("未知产品");
                            orderVO.setImg("");
                        }
                    } else {
                        orderVO.setProductName("未知产品");
                        orderVO.setImg("");
                    }
                    return orderVO;
                })
                .peek(order -> {
                    String codeStr = stringRedisTemplate.opsForValue().get("order:" + order.getId());
                    if (codeStr != null) {
                        order.setQrCodeBase64(codeStr);
                    }
                })
                .collect(Collectors.toList());

        // 7. 构建分页结果
        PageResult pageResult = new PageResult();
        pageResult.setRecords(orderVos);
        pageResult.setRecords(orderVos);
        pageResult.setTotal(orderPage.getTotal());

        return pageResult;
    }

    private static String getStatusText(Integer status) {
        return switch (status) {
            case 0 -> "待付款";
            case 1 -> "待出行";
            case 2 -> "已取消";
            case 3 -> "已完成";
            default -> "未知";
        };
    }


    @Override
    public OrderVO getOrderInfoById(Integer ticketId) {
        TravelRegistration registration = getById(ticketId);
        if (ObjectUtil.isEmpty(registration)){
            throw new BusinessException("报名信息不存在");
        }
        TravelProducts travelProducts = travelProductService.getById(registration.getProductId());
        if (ObjectUtil.isEmpty(travelProducts)){
            throw new BusinessException("产品不存在");
        }
        OrderVO orderVO = BeanUtil.copyProperties(registration, OrderVO.class);
        orderVO.setStatusText(getStatusText(registration.getStatus()));
        orderVO.setProductName(travelProducts.getName());
        orderVO.setImg(travelProducts.getImageUrl());
        orderVO.setDescription(travelProducts.getDescription());
        orderVO.setQrCodeBase64(stringRedisTemplate.opsForValue().get("order:" + orderVO.getOrderNo()));
        orderVO.setPhone(registration.getPhone());
        Integer userId = registration.getUserId();
        Member member = memberService.getById(userId);
        if (ObjectUtil.isEmpty( member)){
            throw new BusinessException("用户不存在");
        }
        orderVO.setName(member.getName());
        return orderVO;
    }

    @Override
    public String createQrCode(QrCodeDto qrCodeData) {
        // 生成二维码
        String orderInfo = "{\"ticketId\":\"" + qrCodeData.getTicketId() +
                "\",\"status\":\"" + qrCodeData.getStatus() + "\"}";
        String codeToBase64 = qrCodeService.createCodeToBase64(orderInfo);
        // 存入redis缓存
        String key = "order:" + qrCodeData.getTicketId();
        stringRedisTemplate.opsForValue().set(key, codeToBase64, 3, TimeUnit.DAYS);
        return codeToBase64;
    }

    @Override
    public void updateStatusByQrCode(QrCodeDto qrCodeData) {
        String key = "order:" + qrCodeData.getTicketId();
        String strEwm = stringRedisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(strEwm)){
            throw new BusinessException("已核销");
        }
        //
        // 1. 校验二维码信息合法性（订单号存在性、状态有效性等）
        LambdaQueryWrapper<TravelRegistration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TravelRegistration::getId, qrCodeData.getTicketId());
        TravelRegistration registration = getOne(queryWrapper);
        if (ObjectUtil.isEmpty(registration)){
            throw new BusinessException("订单不存在");
        }


        // 3. 更新订单状态
        LambdaUpdateWrapper<TravelRegistration> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(TravelRegistration::getStatus, "3");
        updateWrapper.eq(TravelRegistration::getId, qrCodeData.getTicketId());
        boolean success = update(updateWrapper);
        if (!success){
            throw new BusinessException("更新失败");
        }
        // 删除redis中的
        stringRedisTemplate.delete(key);
    }

    @Override
    public PageResult getOrderInfoListForAdmin(Integer pageNum, Integer pageSize, String status) {
        // 1. 构建分页对象 - 问题点：pageSize未校验，默认值可能导致分页不符预期
        Page<TravelRegistration> page = new Page<>(pageNum, pageSize);

        // 2. 构建查询条件
        LambdaQueryWrapper<TravelRegistration> queryWrapper = new LambdaQueryWrapper<>();


        // 按支付状态查询
        if (!StrUtil.isEmpty(status)) {
            queryWrapper.eq(TravelRegistration::getStatus, status);
        }


        // 添加时间排序（降序）
        queryWrapper.orderByDesc(TravelRegistration::getCreateTime);

        // 3. 执行分页查询
        IPage<TravelRegistration> orderPage = travelOrderInfoMapper.selectPage(page, queryWrapper);

        // 打印分页查询关键参数和结果，用于调试
        System.out.println("分页查询参数：pageNum=" + pageNum + ", pageSize=" + pageSize);
        System.out.println("查询结果：total=" + orderPage.getTotal() + ", size=" + orderPage.getSize()
                + ", current=" + orderPage.getCurrent() + ", pages=" + orderPage.getPages());

        // 如果没有订单记录，直接返回空结果
        if (orderPage.getRecords().isEmpty()) {
            return new PageResult();
        }

        // 4. 提取所有订单关联的产品ID
        List<Integer> productIds = orderPage.getRecords().stream()
                .map(TravelRegistration::getProductId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // 5. 使用MP批量查询产品名称和图片
        Map<Integer, TravelProductDTO> productMap;
        if (!productIds.isEmpty()) {
            LambdaQueryWrapper<TravelProducts> productQueryWrapper = new LambdaQueryWrapper<>();
            productQueryWrapper.in(TravelProducts::getId, productIds)
                    .select(TravelProducts::getId, TravelProducts::getName, TravelProducts::getImageUrl);

            List<TravelProducts> products = travelProductService.list(productQueryWrapper);

            productMap = products.stream()
                    .collect(Collectors.toMap(
                            TravelProducts::getId,
                            product -> {
                                TravelProductDTO dto = new TravelProductDTO();
                                dto.setId(product.getId());
                                dto.setName(product.getName());
                                dto.setImageUrl(product.getImageUrl());
                                return dto;
                            }
                    ));
        } else {
            productMap = new HashMap<>();
        }

        // 6. 转换结果为VO对象并设置相关属性
        List<OrderVO> orderVos = orderPage.getRecords().stream()
                .map(order -> {
                    OrderVO orderVO = BeanUtil.copyProperties(order, OrderVO.class);
                    orderVO.setStatusText(getStatusText(order.getStatus()));

                    if (order.getProductId() != null) {
                        TravelProductDTO product = productMap.getOrDefault(order.getProductId(), null);
                        if (product != null) {
                            orderVO.setProductName(product.getName());
                            orderVO.setImg(product.getImageUrl());
                        } else {
                            orderVO.setProductName("未知产品");
                            orderVO.setImg("");
                        }
                    } else {
                        orderVO.setProductName("未知产品");
                        orderVO.setImg("");
                    }
                    return orderVO;
                })
                .peek(order -> {
                    String codeStr = stringRedisTemplate.opsForValue().get("order:" + order.getId());
                    if (codeStr != null) {
                        order.setQrCodeBase64(codeStr);
                    }
                })
                .collect(Collectors.toList());

        // 7. 构建分页结果
        PageResult pageResult = new PageResult();
        pageResult.setRecords(orderVos);
        pageResult.setRecords(orderVos);
        pageResult.setTotal(orderPage.getTotal());

        return pageResult;
    }
}
